package com.xavier.convertor;

import cn.hutool.core.util.ObjectUtil;
import com.xavier.dto.MenuDTO;
import com.xavier.enums.MenuTypeEnum;
import com.xavier.model.Menu;
import com.xavier.utils.BeanUtil;
import com.xavier.utils.TreeUtil;
import com.xavier.vo.MenuDetailVO;
import com.xavier.vo.MenuPageVO;
import com.xavier.vo.RouterMetaVO;
import com.xavier.vo.RouterVO;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 菜单对象相互转换
 *
 * @author Xavier
 * @version 1.0
 */
public abstract class MenuConvertor {

    public static Map<String, Object> toMap(List<Menu> beanList) {
        Map<String, Object> map = new HashMap<>();
        List<RouterVO> menuVoList = new ArrayList<>();
        List<String> permissions = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(beanList)) {
            menuVoList = toTree(beanList, permissions);
        }
        map.put("menus", menuVoList);
        map.put("perms", permissions);
        return map;
    }

    public static List<RouterVO> toTree(List<Menu> menuList, List<String> permissions) {
        List<RouterVO> topList = Collections.EMPTY_LIST;
        if (ObjectUtil.isNotEmpty(menuList)) {
            Map<Long, Menu> map = menuList.stream().collect(Collectors.toMap(Menu::getId, Function.identity()));
            topList = toRouterVO(menuList.stream().filter(bean -> (ObjectUtil.isEmpty(bean.getParentId()) || !map.containsKey(bean.getParentId())) && (MenuTypeEnum.DIRECTORY.equal(bean.getMenuType()) || MenuTypeEnum.MENU.equal(bean.getMenuType())))
                    .sorted(Comparator.comparing(Menu::getSortNumber)).collect(Collectors.toList()));
            List<RouterVO> childList = toRouterVO(menuList.stream().filter(bean -> ObjectUtil.isNotEmpty(bean.getParentId())).collect(Collectors.toList()));
            sort(topList, childList, permissions);

            return topList;
        }
        return topList;
    }

    private static void sort(List<RouterVO> topList, List<RouterVO> childList, List<String> permissions) {
        if (ObjectUtil.isNotEmpty(childList) && ObjectUtil.isNotEmpty(topList)) {
            List<RouterVO> copyVos = BeanUtil.beanCopy(childList, RouterVO.class);
            for (RouterVO top : topList) {
                for (RouterVO child : childList) {
                    if (Objects.equals(top.getId(), child.getParentId())) {
                        child.setMenuCode(top.getMenuCode() + ":" + child.getMenuCode());
                        permissions.add(child.getMenuCode());
                        if (MenuTypeEnum.INTERFACE.equal(child.getMeta().getType())) {
                            continue;
                        }
                        child.setPath(top.getPath() + child.getPath());
                        top.addChildren(child);
                        copyVos.remove(child);
                    }
                }
            }
            for (RouterVO top : topList) {
                if (ObjectUtil.isNotEmpty(top.getChildren())) {
                    top.setChildren(top.getChildren().stream().sorted(Comparator.comparing(RouterVO::getSortNumber)).collect(Collectors.toList()));
                    sort(top.getChildren(), copyVos, permissions);
                }
            }
        }
    }

    public static List<RouterVO> toRouterVO(List<Menu> menuList) {
        if (ObjectUtil.isEmpty(menuList)) {
            return null;
        }
        List<RouterVO> voList = new ArrayList<>();
        for (Menu menu : menuList) {
            RouterVO routerVO = BeanUtil.beanCopy(menu, RouterVO.class);
            routerVO.setName(menu.getMenuName());
            if (MenuTypeEnum.DIRECTORY.equal(menu.getMenuType()) || MenuTypeEnum.MENU.equal(menu.getMenuType())) {
                if (!menu.getIsExt()) {
                    routerVO.setPath(menu.getUrl().startsWith("/") ? "" : "/" + menu.getUrl());
                }
            }
            RouterMetaVO metaVO = BeanUtil.beanCopy(menu, RouterMetaVO.class);
            metaVO.setTitle(menu.getMenuName());
            metaVO.setType(menu.getMenuType());
            routerVO.setMeta(metaVO);
            voList.add(routerVO);
        }
        return voList;
    }

    public static MenuDetailVO toMenuDetailVO(Menu menu) {
        if (Objects.isNull(menu)) {
            return null;
        }
        MenuDetailVO vo = BeanUtil.beanCopy(menu, MenuDetailVO.class);
        return vo;
    }

    public static Menu toMenu(MenuDTO dto) {
        if (Objects.isNull(dto)) {
            return null;
        }
        Menu menu = BeanUtil.beanCopy(dto, Menu.class);
        return menu;
    }

    public static List<MenuPageVO> toMenuPageVOList(List<Menu> menuList) {
        if (ObjectUtil.isEmpty(menuList)) {
            return new ArrayList<>();
        }
        try {
            List<MenuPageVO> menuPageVOS = TreeUtil.listToTree(BeanUtil.beanCopy(menuList.stream().sorted(Comparator.comparing(Menu::getSortNumber)).collect(Collectors.toList()), MenuPageVO.class));
            return menuPageVOS;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

//        Map<Long, Menu> map = menuList.stream().collect(Collectors.toMap(Menu::getId, Function.identity()));
//        List<MenuPageVO> childList = BeanUtil.beanCopy(menuList.stream().filter(bean -> ObjectUtil.isNotEmpty(bean.getParentId())).collect(Collectors.toList()), MenuPageVO.class);
//        sortPage(topList, childList);
//        return topList;
    }


}
